Skip to content

Conversation

marco-saia-datadog
Copy link
Member

What does this PR do?

Starting from v3, we are changing the way attributes are handled to improve safety, consistency and compatibility with native SDKs, and to support more attribute typesl

What’s New

  • Unsupported values (functions, symbols, non-finite numbers, etc.) are automatically dropped, with warnings, to prevent crashes in native SDKs.
  • Common types such as Date, Error, and Map are properly serialized
  • Nested objects are automatically flattened into dot syntax (a.b.c = value), matching the format expected by native SDKs and avoiding ambiguous outcomes.
  • Custom encoders can be registered by users to support domain-specific types.
  • Primitives and arrays at the root are wrapped under a context key to maintain schema consistency.

Motivation

In React Native, it’s common for developers to pass complex objects as attributes (e.g. partial or full Redux/Zustand state, raw Error objects). These may contain unserializable values that would break serialization. While ideally users should only pass clean dictionaries of encodable values, in practice they expect the SDK to handle arbitrary objects to some extent.

This change ensures:

  • Everything passed from JS to native is safe and JSON-serializable
  • Flattening happens in JS, so users don’t need to handle dot syntax manually (which is not idiomatic in React Native), and we don't have to rely on the native SDKs either
  • Ambiguities between nested objects and dot-syntax keys are avoided

Example Transformations

  • "foo"{ context: "foo" }

  • { user: { profile: { name: "Alice" } } }{ "user.profile.name": "Alice" }

  • new Error("Boom"){ "context.name": "Error", "context.message": "Boom", "context.stack": "...", ... }

  • new Map([["k1", 1], ["k2", "v2"]])

    {
      "context": [
        { "key": "k1", "keyType": "string", "value": 1 },
        { "key": "k2", "keyType": "string", "value": "v2" }
      ]
    }
  • Unsupported values like Symbol("x") or () => {}{} (dropped with warning)

Benchmarks

  • Flat/nested objects: ~1M ops/sec
  • Deeply nested objects (20+ levels): ~233k ops/sec
  • Maps with mixed keys: ~405k ops/sec
  • Arrays of objects: ~28k–33k ops/sec (expectedly slower due to recursion)

@marco-saia-datadog marco-saia-datadog force-pushed the marcosaia/RUM-10500/v3-context-validation branch from d9f921e to 68036d3 Compare October 10, 2025 10:27
@marco-saia-datadog marco-saia-datadog force-pushed the marcosaia/RUM-10500/v3-context-validation branch from 68036d3 to a4725c4 Compare October 10, 2025 10:29
sbarrio
sbarrio previously approved these changes Oct 13, 2025
Copy link
Contributor

@sbarrio sbarrio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some minor comments. Good work!

@marco-saia-datadog
Copy link
Member Author

Thanks @sbarrio 🙌 I have addressed your comments in a new commit. I still have to do some further manual testing before merging this. After I am done, I will squash the commits and merge this in v3 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants